package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"spam3uk/internal/api"
	"spam3uk/internal/config"
	"spam3uk/internal/models"
	"spam3uk/internal/storage"
	"time"

	"github.com/sirupsen/logrus"
	"gopkg.in/natefinch/lumberjack.v2"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func main() {
	// 加载配置 - 支持环境变量覆盖
	configFile := getConfigFile()
	log.Printf("Loading config from: %s", configFile)

	cfg, err := config.LoadConfig(configFile)
	if err != nil {
		log.Fatalf("Failed to load config: %v", err)
	}
	log.Printf("Config loaded successfully")

	// 验证配置
	log.Printf("Validating config...")
	if err := validateConfig(cfg); err != nil {
		log.Fatalf("Config validation failed: %v", err)
	}
	log.Printf("Config validation passed")

	// 初始化日志
	log.Printf("Initializing logger...")
	logger := logrus.New()
	logger.SetFormatter(&logrus.TextFormatter{FullTimestamp: true})
	level, err := logrus.ParseLevel(cfg.Logger.Level)
	if err != nil {
		level = logrus.InfoLevel
		log.Printf("Warning: Failed to parse log level, using InfoLevel: %v", err)
	}
	logger.SetLevel(level)
	log.Printf("Logger level set to: %s", level)

	// 配置日志输出 - 支持同时输出到控制台和文件
	if cfg.Logger.Output.File.Enabled {
		log.Printf("Configuring file logging...")
		logPath := cfg.Logger.Output.File.Path
		if logPath == "" {
			logPath = "logs"
		}
		if err := os.MkdirAll(logPath, 0o755); err != nil {
			log.Printf("Warning: Failed to create log directory: %v", err)
		} else {
			// 配置文件输出
			fileLogger := &lumberjack.Logger{
				Filename:   fmt.Sprintf("%s/%s.log", logPath, cfg.Logger.Output.File.Filename),
				MaxSize:    cfg.Logger.Output.File.MaxSize,
				MaxBackups: cfg.Logger.Output.File.MaxBackups,
				MaxAge:     cfg.Logger.Output.File.MaxAge,
				Compress:   cfg.Logger.Output.File.Compress,
			}

			// 如果控制台输出也启用，使用MultiWriter同时输出到控制台和文件
			if cfg.Logger.Output.Console.Enabled {
				logger.SetOutput(io.MultiWriter(os.Stdout, fileLogger))
				log.Printf("File and console logging configured")
			} else {
				logger.SetOutput(fileLogger)
				log.Printf("File logging configured (console disabled)")
			}
		}
	} else {
		log.Printf("File logging disabled, using console only")
	}

	logger.Info("Starting SPAM3-UK Ford Vehicle Scraper Service")
	logger.Infof("Config loaded: %s v%s", cfg.App.Name, cfg.App.Version)
	logger.Infof("Environment: %s", cfg.App.Environment)

	// 初始化数据库连接
	db, err := initDatabase(cfg, logger)
	if err != nil {
		logger.Fatalf("Failed to initialize database: %v", err)
	}

	// 初始化存储
	vehicleStorage := storage.NewMySQLStorage(db)

	// 设置路由
	router := api.SetupRoutes(vehicleStorage, logger, cfg.App.Version)

	// 启动前打印启动摘要信息
	printStartupSummary(logger, cfg, db)

	// 启动服务器
	addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)
	logger.Infof("Server starting on %s", addr)
	logger.Infof("Registered endpoints:")
	for _, r := range router.Routes() {
		logger.Infof("  %s %s", r.Method, r.Path)
	}

	if err := router.Run(addr); err != nil {
		logger.Fatalf("Failed to start server: %v", err)
	}
}

// printStartupSummary 打印一页式启动摘要，便于观察服务已正常启动
func printStartupSummary(logger *logrus.Logger, cfg *config.Config, db *gorm.DB) {
	// 统计数据库中的现有数据量
	var totalVehicles int64
	var totalTrims int64
	_ = db.Model(&models.VehicleInfo{}).Count(&totalVehicles).Error
	_ = db.Model(&models.TrimInfo{}).Count(&totalTrims).Error

	banner := "\n" +
		"==============================================================\n" +
		"  SPAM3-UK Service Started\n" +
		"--------------------------------------------------------------\n" +
		fmt.Sprintf("  App:        %s  v%s\n", cfg.App.Name, cfg.App.Version) +
		fmt.Sprintf("  Env/Mode:   %s / %s\n", cfg.App.Environment, cfg.App.Mode) +
		fmt.Sprintf("  Listen:     http://%s:%d\n", cfg.Server.Host, cfg.Server.Port) +
		"\n" +
		fmt.Sprintf("  DB:         %s@%s:%d/%s\n", cfg.Database.Username, cfg.Database.Host, cfg.Database.Port, cfg.Database.Database) +
		fmt.Sprintf("  Tables:     vehicles=%d, trims=%d\n", totalVehicles, totalTrims) +
		"\n" +
		"  Health:     GET /health\n" +
		"  UI:         GET /web   (or /)\n" +
		"  Vehicles:   GET /api/vehicles\n" +
		"  Trims:      GET /api/get_trims?model=Puma\n" +
		"  ScrapeAll:  POST /api/scrape_all\n" +
		"\n" +
		"  Examples:\n" +
		fmt.Sprintf("    curl \"http://%s:%d/health\"\n", cfg.Server.Host, cfg.Server.Port) +
		fmt.Sprintf("    curl \"http://%s:%d/api/vehicles?page=1&page_size=5\"\n", cfg.Server.Host, cfg.Server.Port) +
		fmt.Sprintf("    curl \"http://%s:%d/api/get_trims?model=Focus\"\n", cfg.Server.Host, cfg.Server.Port) +
		"==============================================================\n"

	logger.Info(banner)
}

// getConfigFile 获取配置文件路径，支持环境变量覆盖
func getConfigFile() string {
	// 支持环境变量覆盖
	if envConfig := os.Getenv("SPAM3UK_CONFIG"); envConfig != "" {
		return envConfig
	}

	// 检查生产配置文件（项目专用命名）
	if _, err := os.Stat("spam3uk-config.prod.json"); err == nil {
		return "spam3uk-config.prod.json"
	}

	// 默认配置文件
	return "spam3uk-config.json"
}

// validateConfig 验证配置文件的必要字段
func validateConfig(cfg *config.Config) error {
	if cfg.App.Name == "" {
		return fmt.Errorf("app name is required")
	}
	if cfg.Server.Port <= 0 {
		return fmt.Errorf("server port must be greater than 0")
	}
	if cfg.Database.Host == "" {
		return fmt.Errorf("database host is required")
	}
	if cfg.Database.Database == "" {
		return fmt.Errorf("database name is required")
	}
	return nil
}

// initDatabase 初始化数据库连接
func initDatabase(cfg *config.Config, logger *logrus.Logger) (*gorm.DB, error) {
	logger.Info("Connecting to database...")

	dsn := cfg.Database.GetDSN()

	// 配置数据库连接池
	gormConfig := &gorm.Config{}

	// 获取数据库连接
	db, err := gorm.Open(mysql.Open(dsn), gormConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to connect to database: %w", err)
	}

	// 配置连接池参数
	sqlDB, err := db.DB()
	if err != nil {
		return nil, fmt.Errorf("failed to get underlying sql.DB: %w", err)
	}

	// 应用连接池配置
	if cfg.Database.ConnectionPool.MaxOpenConnections > 0 {
		sqlDB.SetMaxOpenConns(cfg.Database.ConnectionPool.MaxOpenConnections)
		logger.Infof("Set max open connections: %d", cfg.Database.ConnectionPool.MaxOpenConnections)
	}

	if cfg.Database.ConnectionPool.MaxIdleConnections > 0 {
		sqlDB.SetMaxIdleConns(cfg.Database.ConnectionPool.MaxIdleConnections)
		logger.Infof("Set max idle connections: %d", cfg.Database.ConnectionPool.MaxIdleConnections)
	}

	if cfg.Database.ConnectionPool.ConnectionMaxLifetime > 0 {
		sqlDB.SetConnMaxLifetime(time.Duration(cfg.Database.ConnectionPool.ConnectionMaxLifetime) * time.Second)
		logger.Infof("Set connection max lifetime: %d seconds", cfg.Database.ConnectionPool.ConnectionMaxLifetime)
	}

	// 自动迁移
	logger.Info("Running database migrations...")
	if err := db.AutoMigrate(&models.VehicleInfo{}, &models.TrimInfo{}, &models.TrimSpecsInfo{}); err != nil {
		return nil, fmt.Errorf("failed to migrate database: %w", err)
	}

	logger.Info("Database connected and migrated successfully")
	return db, nil
}
